Surface绘图缓冲区的创建流程

Android View绘制是GUI系统的核心,而绘制view是需要缓冲区的,也就是我们说的画布,因此了解这个缓冲区的分配流程是有必要的,本篇将对该缓冲区的分配进行解释。

Activity结构剖析

Acitivty实际上在WMS端只是个Window,是以WindowState进行描述的,在AMS端它是一个ActivityRecord,在Activity内部它持有一个mWindow,它实际上为一个PhoneWindow实例,在PhoneWindow中维护了一个DecorView,也就是view树,这个PhoneWindow实例由一个WindowManagerImpl进行管理,在WindowManagaerImpl内部持有一个WindowManagerGlobal单例,它内部持有WMS的本地代理IWindowManager和由其打开的一个IWindowSession负责和WMS进行会话,另一方面它负责整个应用的窗口视图的管理,也就是DecorView及ViewRootImpl的管理。每个新添加的window最终会在WMS端以WidowState的形式存在于WMS,WMS不关心window的View树的内容,它只关心Window的大小样式以及Z序等,而绘制的流程是由我们应用程序进行的,实际上就是由ViewRootImp进行绘制的。那么相应的ViewRootImpl在进行绘制前是需要一个画布进行view树的绘制的,这个画布就是Surface。接下来我们将围绕这个Surface进行话题的展开。

画布的分配

在ViewRootImpl创建时同时会new一个Surface对象

1
private final Surface mSurface = new Surface();

接下来我们看下这个Surface的内部会做些什么。

1
2
3
4
5
6
7
8
9
10
11
public class Surface implements Parcelable {
^
int mNativeObject; // package scope only for SurfaceControl access
private int mLockedObject;
private int mGenerationId; // incremented each time mNativeObject changes
private final Canvas mCanvas = new CompatibleCanvas();
……
public Surface() {
}
……
}

可以看到Surface的构造方法只是个空实现,而貌似mCanvas可能会是真正的画布,我们继续看看Canvas的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Canvas {
/** @hide */
public int mNativeCanvas;
// may be null
private Bitmap mBitmap;
// optional field set by the caller
private DrawFilter mDrawFilter;
……
public Canvas() {
if (!isHardwareAccelerated()) {
// 0 means no native bitmap
mNativeCanvas = initRaster(0);
mFinalizer = new CanvasFinalizer(mNativeCanvas);
} else {
mFinalizer = null;
}
}
……
}

在Canava的构造方法中也并没有相关缓冲区分配的动作,这么说new出来的Surface并非真的分派了缓冲区,而只是一个空壳。想想也就能理解,我们知道ViewRootImpl分派的时机是WindowManagerGlobal通过addView来添加view树的时候分配的时候,这时候WMS还不知道这个Window的存在的(最起码得知道分配多大吧),那么给view树分配缓冲区的确为时过早。那么什么时候分配合适呢?当然是准备绘制view树的时候。view树的绘制是在performTraversal中进行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;//viewRoot管理的view树 decorView
……
boolean windowShouldResize = layoutRequested && windowSizeMayChange
&& ((mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight())
|| (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT &&
frame.width() < desiredWindowWidth && frame.width() != mWidth)
|| (lp.height == ViewGroup.LayoutParams.WRAP_CONTENT &&
frame.height() < desiredWindowHeight && frame.height() != mHeight));
……
if (mFirst || windowShouldResize || insetsChanged ||
viewVisibilityChanged || params != null || mConfigurationChanged) {
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
……
}
……
performMeasure();
……
performLayout();
……
performDraw();
}

performTraversals函数比较长,我这里只取跟本篇相关的内容,在performTraversals并非仅仅只有三大绘制流程performMeasure,performLayout和performDraw,实际上在这三个流程之前还是做了很多事情的,我简单的说下:

  1. 计算期望的窗口大小,如果Window带状态栏,那么在其大小中应该除去状态栏的那部分宽高。否则大小应该为整个屏幕的大小

  2. 如果窗口大小发生了变化也需要记录下来

  3. 计算窗口的内容区域边衬是否变化

  4. 如果可见性发生了变化也需要记录,同时通知view树子视图可见性发生了变化

  5. 根据条件判断是否需要relayoutWindow,在relayoutWindow中会重新计算窗口大小。需要满足的条件至少为以下一种:

     <1>. Activity窗口是第一次执行测量、布局和绘制操作,即ViewRoot类的成员变量mFirst的值等于true。
     
     <2>. 前面得到的变量windowShouldResize的值等于true,即Activity窗口的大小的确是发生了变化。
     
     <3>. 前面得到的变量insetsChanged的值等于true,即Activity窗口的内容区域边衬发生了变化。
     
     <4>. Activity窗口的可见性发生了变化,即变量viewVisibilityChanged的值等于true。
     
     <5>. Activity窗口的属性发生了变化,即变量params指向了一个WindowManager.LayoutParams对象
    

6.执行绘制流程,这个在另外的篇幅再做介绍

在relayoutWindow中会计算窗口的大小,同时这里会为窗口分配缓冲区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {

……
int relayoutResult = mWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface);

……
return relayoutResult;
}

通过mWindowSession和WMS进行会话调用relayout计算窗口的大小并将mSurface传递给WMS。IWindowSession的服务端为Session,我们看看它的实现

1
2
3
4
5
6
7
8
9
10
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outConfig, outSurface);//调用WMS的relayoutWindow
return res;
}

Session的relayout会通过WMS的relayoutWindow来完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {

synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return 0;
}
WindowStateAnimator winAnimator = win.mWinAnimator;

……
try {
if (!win.mHasSurface) {
surfaceChanged = true;
}
//创建SurfaceControl 准备画布
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
}
……
}

}

relayoutWindow的参树client为ViewRootImpl传递的W对象,是一个Binder对象,WMS通过client来通知应用窗口的变化。最后一个参数从命名上来看,它是一个出参,也就是通过这个方法可以拿到真正可用的Surface。可以看到outSurface是由copyFrom从SurfaceControl得来的。这个surfaceControl是通过winAnimator.createSurfaceLocked()来创建的。这个winAnimator是一个WindowStateAnimator,在我们为Window创建WindowState时创建的,它和WindowState是一一对应的。

1
2
3
4
5
6
7
8
9
10
11
12
frameworks/base/services/java/com/android/server/wm/WindowStateAnimator.java
SurfaceControl createSurfaceLocked() {
if (mSurfaceControl == null) {
……
mSurfaceControl = new SurfaceControl(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
w, h, format, flags);
……
}
return mSurfaceControl;
}

mSurfaceControl在WindowStateAnimator中只会创建一次,这里的mSession实际上就是应用端和WMS进行会话的session,即IWindowSession,在创建时会指定缓冲区大小,格式以及标记。那么mSurfaceSession是什么呢,在哪里创建的呢?我们继续看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
//为客户端创建一个Session会话,后面客户端使用这个Session同WMS进行会话
@Override
public IWindowSession openSession(IInputMethodClient client,
IInputContext inputContext) {
Session session = new Session(this, client, inputContext);
return session;
}

public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, InputChannel outInputChannel) {
……
win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
……
win.attach()
……
}
1
2
3
4
5
6
7
frameworks/base/services/java/com/android/server/wm/WindowState.java
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
1
2
3
4
5
6
7
8
frameworks/base/services/java/com/android/server/wm/Session.java
void windowAddedLocked() {
if (mSurfaceSession == null) {
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
}
mNumWindow++;
}

在WMS为应用打开一个会话session后并没有立马去创建mSurfaceSession,而是在Window添加到WMS的时候创建完WindowState后通过attach方法创建的。它同样的对于一个Session只会创建一个,也就是说我们的应用程序只会有一个SurfaceSession,因为它是Session的成员嘛。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public final class SurfaceSession {
// Note: This field is accessed by native code.
private int mNativeClient; // SurfaceComposerClient*

private static native int nativeCreate();
private static native void nativeDestroy(int ptr);
private static native void nativeKill(int ptr);

/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}

……
}

SurfaceSession的实现很简单,因为它的工作都放在native层完成了。

1
2
3
4
5
6
frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();//SurfaceComposerClient是处于客户端的
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jint>(client);
}

实际上它是创建了一个SurfaceComposerClient对象并放在mNativeClient中。这个对象是用来和SurfaceFlinger打交道的,但它并不是SurfaceFlinger的本地代理。SurfaceFlinger负责界面图层的合成,这之间会涉及我们的缓冲区,所以分配缓冲区的工作需要经过SurfaceFlinger来进行。

弄清楚SurfaceSession是什么后,接下来我们看SurfaceControl的创建,它会用到SurfaceSession。

1
2
3
4
5
6
7
8
9
public class SurfaceControl {
int mNativeObject;
public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
mName = name;
mNativeObject = nativeCreate(session, name, w, h, format, flags);//通过native层创建SurfaceControl
}
}

同样的,它的工作也是在native层进行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
sp<SurfaceControl> surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);//创建SurfaceHolder
if (surface == NULL) {
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
surface->incStrong((void *)nativeCreate);
return int(surface.get());//这里返回创建的SurfaceControl
}
1
2
3
4
5
6
frameworks/base/core/jni/android_view_SurfaceSession.cpp
sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast<SurfaceComposerClient*>(
env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}

在nativeCreate中首先通过android_view_SurfaceSession_getClient从SurfaceSession中取到之前创建的SurfaceComoserClient对象,然后通过该对象调用的CreateSurface创建SurfaceControl。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sm(ComposerService::getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();//与surfaceflinger建立连接
if (conn != 0) {
mClient = conn;//mClient对应服务端Client
mStatus = NO_ERROR;
}
}
}

sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();//实例采用单例
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {//获取surfaceflinger服务
usleep(250000);
}
……
}

sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
status_t err = mClient->createSurface(name, w, h, format, flags,
&handle, &gbp);//在Client服务端创建相应的Layer
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);//同时创建一个SurfaceControl,这个gbp即是对应Layer的BufferQueue
}
}
return sur;
}

SurfaceComposerClient在创建完后,强引用的会首先会执行onFirstRef 在这个方法里会通过
ComposerService::getComposerService获取到SurfaceFlinger的Binder本地代理sm,这是在ComposerService::connectLocked中通过getService获取的,SurfaceFlinger是实名Binder,因此可以通过ServiceManager查询得到。获取到SurfaceFlinger的本地代理后,就可以通过createConnection创建ISurfaceComposerClient,它是一个匿名Binder,是SurfaceFlinger服务中Client 的本地代理。Client也是个Binder Server,SurfaceFlinger为每个于其建立连接的应用进程维护一个Client便于管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
frameworks/native/services/surfaceflinger/Client.cpp
//应用程序创建Surface
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
Client* client;
sp<IBinder>* handle;
sp<IGraphicBufferProducer>* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
: flinger(flinger), client(client),
handle(handle), gbp(gbp),
name(name), w(w), h(h), format(format), flags(flags) {
}
status_t getResult() const { return result; }
//message最终通过这个handler进行处理
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
handle, gbp);//创建过程由sf的createLayer完成,客户端创建一个Surface,对应的在sf中创建一个Layer
return true;
}
};

sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);//通过消息队列的方式来处理请求,主要是因为sf是为多个应用服务的,用这样的方式便于处理多个请求。
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

在Client中createSurfac会通过请求参数构造一个MessageBase然后post到SurfaceFlinger的MessageQueue,最终事件会通过MessageBase的handleMessage进行处理,在handleMessage中调用了虚方法handler进行消息的处理。也就是MessageCreateLayer的handler进行处理。

1
2
3
4
void MessageBase::handleMessage(const Message&) {
this->handler();//调用handler方法
barrier.open();
};

在MessageCreateLayer的handler中又会通过SurfaceFlinger的createLayout为客户端创建一个Layer,这个Layer即图层,它对应于应用端的Window。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)//为客户端创建Layer
{
……
sp<Layer> layer;

switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {//支持两种类型的Layer Normal和Dim
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createNormalLayer(client,
name, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceDim:
result = createDimLayer(client,
name, w, h, flags,
handle, gbp, &layer);
break;
default:
result = BAD_VALUE;
break;
}

if (result == NO_ERROR) {
addClientLayer(client, *handle, *gbp, layer);//将创建的Layer添加到用户的队列中
setTransactionFlags(eTransactionNeeded);
}
return result;
}

在SurfaceFlinger的createLayer中会根据flag来创建不同的layer,分别为Normal和Dim类型的,创建完layer后会将其添加到client中去。这里我们看下CreateNormalLayer的实现即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)//创建Normal类型的Layer
{
// initialize the surfaces
switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
#ifdef NO_RGBX_8888
format = PIXEL_FORMAT_RGB_565;
#else
format = PIXEL_FORMAT_RGBX_8888;
#endif
break;
}

#ifdef NO_RGBX_8888
if (format == PIXEL_FORMAT_RGBX_8888)
format = PIXEL_FORMAT_RGBA_8888;
#endif

*outLayer = new Layer(this, client, name, w, h, flags);//创建Layouer 在第一次引用该Layer时会创建其BufferQueue和Consumer
status_t err = (*outLayer)->setBuffers(w, h, format, flags);//设置layer大小和格式
if (err == NO_ERROR) {
*handle = (*outLayer)->getHandle();
*gbp = (*outLayer)->getBufferQueue();//获取Layer对应的BufferQueue
}
return err;
}

创建Layer的实例后就可以通过getBufferQueue获取到layer内部的BufferQueue,这个BufferQueue是个Binder Server,它是一个缓冲队列,用来维护layer的缓冲区。它是在Layer的onFirstRef中创建的,我们缓冲区的分配在SurfaceFligner端实际实际上就是通过它来分配的。同时,它既是缓冲区的消费者又是生产者,对于应用端来说,它扮演生产者的角色,因为应用端是填充数据的一方,而对于surfaceFligner来说它又扮演消费者的角色,因为SurfaceFlinger是合成layer层,取出缓冲区进行显示的。

1
2
3
4
5
6
7
8
9
10
11
12
void Layer::onFirstRef() {//在第一次引用时创建一个bufferqueue
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
mBufferQueue = new SurfaceTextureLayer(mFlinger);//创建一个BufferQueue用于管理Layer的图形缓冲区
……
}

class SurfaceTextureLayer : public BufferQueue {//父类是BufferQueue
sp<SurfaceFlinger> flinger;
public:
SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
virtual ~SurfaceTextureLayer();
};

这里的SurfaceTextureLayer它实际上就是个BufferQueue。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
status_t err = mClient->createSurface(name, w, h, format, flags,
&handle, &gbp);//在Client服务端创建相应的Layer
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);//同时创建一个SurfaceControl,这个gbp即是对应Layer的BufferQueue
}
}
return sur;
}

我们创建好layer后通过getBufferQueue后是以IGraphicBufferProducer的角色返回的,它代表了这个BufferQueue将作为一个生产者供应用端使用。紧接着在本地创建一个SurfaceControl
需要注意这个时候gbd是在我们的应用进程中了,它是BufferQueue的本地代理binder对象了。
我们通过这个代理对象来创建SurfaceControl。

1
2
3
4
5
6
7
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbp)
: mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}

这里我们创建好本地的SurfaceControl,然后保存在java层的SurfaceControl的mNativeObject中。但是这个时候好像并没有真正去分配缓冲区,那么创建这个SurfaceControl给上层到底是干嘛用的?没错,就是用来分配缓冲区的,因为它内部这时候是有一个IGraphicBufferProducer的,它是layer中的BufferQueue代理binder。

在WMS的relayoutWindow中创建完SurfaceControl后,会通过Surface的copyFrom来初始化它,在这之前Surface还是个空壳。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Surface implements Parcelable {
……
public void copyFrom(SurfaceControl other) {
if (other == null) {
throw new IllegalArgumentException("other must not be null");
}

int surfaceControlPtr = other.mNativeObject;//取到指向SurfaceControl的本地对象指针
if (surfaceControlPtr == 0) {
throw new NullPointerException(
"SurfaceControl native object is null. Are you using a released SurfaceControl?");
}
int newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);//通过SurfaceControl来创建新的Surface

synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
……
}

java层的Surface是通过nativeCreateFromSurfaceControl,并将native层的SurfaceControl对象指针传递给它。

1
2
3
4
5
6
7
8
9
static jint nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
jint surfaceControlNativeObj) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
sp<Surface> surface(ctrl->getSurface());//返回surfacecontrol管理的surface
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
return reinterpret_cast<jint>(surface.get());
}

通过native层的SurfaceControl指针,可以通过getSurface获取到一个Surface。

1
2
3
4
5
6
7
8
9
10
sp<Surface> SurfaceControl::getSurface() const//获取内部持有的Surface
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {//第一次为空时创建
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);//这个surface是sf中消费的。
}
return mSurfaceData;
}
1
2
3
4
5
6
7
8
9
10
11
12

private void setNativeObjectLocked(int ptr) {
if (mNativeObject != ptr) {
if (mNativeObject == 0 && ptr != 0) {
mCloseGuard.open("release");
} else if (mNativeObject != 0 && ptr == 0) {
mCloseGuard.close();
}
mNativeObject = ptr;
mGenerationId += 1;
}
}

SurfaceControl 并不直接去分配缓冲区,而是通过管理一个本地Surface对象来管理缓冲区,它通过mGraphicBufferProducer构造,这个就是之前我们取到的IGraphicBufferProducer binder代理对象,构造的本地Surface最终会通过setNativeObjectLocked
保存在java层Surface的mNativeObject中。到这里java层的Surface就算创建完了,最终返回给ViewRootImpl使用。

Surface的使用

从Surface中取缓冲区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff,
boolean scalingRequired, Rect dirty) {
Canvas canvas;
……
canvas = mSurface.lockCanvas(dirty);
try {
……
mView.draw(canvas);
} finally {
try {
surface.unlockCanvasAndPost(canvas);
}
}
return true;
}

Surface首先通过lockCanvas获取到一个Canvas对象,这个Canvas实际上为就是通过Surface的缓冲区填充的画布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public Canvas lockCanvas(Rect inOutDirty)
throws Surface.OutOfResourcesException, IllegalArgumentException {
synchronized (mLock) {
……
mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
return mCanvas;
}
}

//jni层的surface lockCanvas调用
static jint nativeLockCanvas(JNIEnv* env, jclass clazz,
jint nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));//这个surface由surfaceControl创建的
if (!isSurfaceValid(surface)) {
doThrowIAE(env);
return 0;
}

Rect dirtyRect;
Rect* dirtyRectPtr = NULL;

if (dirtyRectObj) {
dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
dirtyRectPtr = &dirtyRect;
}

ANativeWindow_Buffer outBuffer;//ANativeWindow_Buffer定义在native_window.h中
status_t err = surface->lock(&outBuffer, dirtyRectPtr);
if (err < 0) {
const char* const exception = (err == NO_MEMORY) ?
OutOfResourcesException :
"java/lang/IllegalArgumentException";
jniThrowException(env, exception, NULL);
return 0;
}

// Associate a SkCanvas object to this surface
env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);//将skCanvas是关联到surface
SkBitmap bitmap;//准备画布
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);//设置画布大小及格式
if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
bitmap.setAlphaType(kOpaque_SkAlphaType);
}
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);//给画布设置缓冲区
} else {
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
}

SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));//将画布作为native的Canvase返回给上层使用
swapCanvasPtr(env, canvasObj, nativeCanvas);

if (dirtyRectPtr) {
nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
}

if (dirtyRectObj) {
env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
}
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (int) lockedSurface.get();
}

Surface的localCanvas是通过nativeLockCanvas,首先通过mNativeObject取到本地的Surface对象,通过这个本地的Surface进行lock取到缓冲区outBuffer,它是一个ANativeWindow_Buffer,随后通过这个缓冲区初始化一个SkBitmap画布,并设置其格式大小等,通过SkBitmap创建一个SkCanvas返回给java层Surface的mCanvas,我们在Draw方法中使用的Canvas就是这个SkCanvas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
……
ANativeWindowBuffer* out;// 定义在window.h
int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd);//分配缓冲区
……
}

//申请图形缓冲区
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
int buf = -1;
int reqW = mReqWidth ? mReqWidth : mUserWidth;
int reqH = mReqHeight ? mReqHeight : mUserHeight;
……
sp<Fence> fence;
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
reqW, reqH, mReqFormat, mReqUsage);
……
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
……
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {//未分配 或者需要重新映射
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);//Surface通过调用 requestBuffer将图形缓冲区映射到Surface所在进程
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
return result;
}
}
……
*buffer = gbuf.get();//获取缓冲区
return OK;
}

首先通过mGraphicBufferProducer通过dequeueBuffer分配缓冲区,实际是由BufferQueue完成的,它实际上是取到BufferQueue中BufferSlot槽的索引buf,有了这个索引,通过requestBuffer就真正的创建buffer并将该buffer映射到Surface所在进程。这样我们的应用程序就可以使用了。

提交绘制好的缓冲区

1
2
3
4
5
6
7
8
9
public void unlockCanvasAndPost(Canvas canvas) {
……
synchronized (mLock) {
……
nativeUnlockCanvasAndPost(mLockedObject, canvas);
nativeRelease(mLockedObject);
mLockedObject = 0;
}
}

同样的应用层绘制完后,需要将该缓冲区unlock并且提交给BufferQueue。这个是通过nativeUnlockCanvasAndPost进行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
jint nativeObject, jobject canvasObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
return;
}

// detach the canvas from the surface
SkCanvas* nativeCanvas = SkNEW(SkCanvas);
swapCanvasPtr(env, canvasObj, nativeCanvas);//把canvas从surface分离

// unlock surface
status_t err = surface->unlockAndPost();//提交结果
if (err < 0) {
doThrowIAE(env);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
status_t Surface::unlockAndPost()//提交Locked的Buffer
{
if (mLockedBuffer == 0) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
status_t err = mLockedBuffer->unlock();
err = queueBuffer(mLockedBuffer.get(), -1);//将该Buffer queue
mPostedBuffer = mLockedBuffer;//locked的buffer变为posted
……
return err;
}

Surfae的unlockAndPost调用queueBuffer方法完成buffer的提交

1
2
3
4
5
6
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {//buffer queue进行消费
……
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);//通过调用GBP的
……
return err;
}

通过mGraphicBufferProducer入队这个buffer,此时生产者的任务完毕,layer端的Consumer即SurfaceFlinger会监听到这个有效的缓冲区,然后准备合成显示layer,最终将绘制的东西显示在屏幕上。

坚持原创技术分享,您的支持将鼓励我继续创作!